home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / vmed.arc / ED10.CCC < prev    next >
Encoding:
Text File  |  1985-12-03  |  8.1 KB  |  356 lines

  1. /*    Screen editor:    buffer module
  2.  *
  3.  *    Module: ed10/ccc
  4.  *    Date: November 14, 1983
  5.  */
  6.  
  7. #include ed0
  8.  
  9. /* data global to this module */
  10.  
  11.  /* Buffer must be declared after all other variables
  12.   * of the entire program.
  13.   * Note: buffer must have nonzero dimension.
  14.   */
  15.  char    bufcflag;    /* main buffer changed flag */
  16.  char    *bufp;    /* start of current line */
  17.  char    *bufpmax;    /* end of last line */
  18.  char    *bufend;    /* last byte of buffer */
  19.  int    bufline;    /* current line number */
  20.  int    bufmaxln;    /* number of lines in buffer */
  21.  char    buffer[1];    /* start of buffer */
  22.  
  23. /* This code is built around several invariant
  24.  * assumptions:
  25.  * First, the last line is always completely empty.
  26.  * When bufp points to the last line there is NO CR
  27.  * following it. Second, bufp points to the last line if
  28.  * and only if bufline == bufmaxln+1. Third, bufline is
  29.  * always greater than zero. Line zero exists only to make
  30.  * scanning for the start of line one easier.
  31.  */
  32.  
  33. /* Clear the main buffer */
  34. bufnew()
  35. {
  36.     /* point past line 0 */
  37.     bufp = bufpmax = buffer + 1;
  38.     /* point at last byte of buffer */
  39.     /* allow room for stack */
  40.     bufend = sysend()-1000;
  41.     /* at line one, no lines in buffer */
  42.     bufline = 1;
  43.     bufmaxln = 0;
  44.     /* line zero is always a null line */
  45.     buffer[0] = CR;
  46.     /* indicate no need to save file yet */
  47.     bufcflag = NO;
  48. }
  49.  
  50. /* return current line number */
  51. bufln()
  52. {    return(bufline);    }
  53.  
  54. /* return YES if the buffer (i.e.. file) has been
  55.  * changed since the last time the file was saved.
  56.  */
  57. bufchng()
  58. {    return(bufcflag);    }
  59.  
  60. /* the file has been saved. clear bufcflag */
  61. bufsaved()
  62. {    bufcflag = NO;    }
  63.  
  64. /* return number of bytes left in the buffer */
  65. buffree()
  66. {    return(bufend - bufp);    }
  67.  
  68. /* position buffer pointers to start of indicated line */
  69. bufgo(line)    int line;
  70. {
  71.     /* put request into range, prevent extension */
  72.     line = min(bufmaxln+1,line);
  73.     line = max(1,line);
  74.     /* already at proper line ? return */
  75.     if (line == bufline)
  76.         return(OK);
  77.     /* move through buffer one line at a line */
  78.     while (line < bufline)
  79.         if (bufup() == ERR)
  80.             return(ERR);
  81.     while (line > bufline)
  82.         if (bufdn() == ERR)
  83.             return(ERR);
  84.     /* we have reached the line we wanted */
  85.     return(OK);
  86. }
  87.  
  88. /* move one line closer to front of buffer, i.e., set
  89.  * buffer pointers to start of previous line.
  90.  */
  91. bufup()
  92. {    char    *oldbufp;
  93.     oldbufp = bufp;
  94.     /* can't move past line 1 */
  95.     if (bufattop())
  96.         return(OK);
  97.     /* move past CR of previous line */
  98.     if (*--bufp != CR)    {
  99.         outm(BUMCR);
  100.         bufp = oldbufp;
  101.         return(ERR);
  102.     }
  103.     /* move to start of previous line */
  104.     while (*--bufp != CR)
  105.         ;
  106.     ++bufp;
  107.     /* make sure we haven't gone too far */
  108.     if (bufp < (buffer + 1))    {
  109.         outm(BUUF);
  110.         bufp = oldbufp;
  111.         return(ERR);
  112.     }
  113.     /* success ! we are at previous line */
  114.     --bufline;
  115.     return(OK);
  116. }
  117.  
  118. /* Move one line closer to end of buffer, i.e.,
  119.  * set buffer pointers to start of next line.
  120.  */
  121. bufdn()
  122. {    char *oldbufp;
  123.     oldbufp = bufp;
  124.     /* do nothing silly if at end of buffer */
  125.     if (bufatbot())
  126.         return(OK);
  127.     /* scan past current line and CR */
  128.     while (*bufp++ != CR);
  129.     /* make sure we haven't gone too far */
  130.     if (bufp > bufpmax)    {
  131.         outm(BDOF);
  132.         bufp = oldbufp;
  133.         return(ERR);
  134.     }
  135.     /* success! we are at next line */
  136.     ++bufline;
  137.     return(OK);
  138. }
  139.  
  140. /* Insert a line before the current line.
  141.  * p points to a line of length n to be inserted.
  142.  * Note: n does not include trailing CR.
  143.  */
  144. bufins(p,n)    char *p;    int n;
  145. {    int    k;
  146.     /* make room in the buffer for the line */
  147.     if (bufext(n + 1) == ERR)
  148.         return(ERR);
  149.     /* put the line and CR into the buffer */
  150.     k = 0;
  151.     while (k < n)    {
  152.         *(bufp + k) = *(p + k);
  153.         ++k;
  154.     }
  155.     *(bufp + k) = CR;
  156.     /* increase number of lines in buffer */
  157.     ++bufmaxln;
  158.     /* special case: inserting a null line at
  159.      * end of file is not a significant change.
  160.      */
  161.     if ((n == 0) & (bufnrbot()))
  162.         ;
  163.     else    bufcflag = YES;
  164.     return(OK);
  165. }
  166.  
  167. /* delete the current line */
  168. bufdel()
  169. {    return(bufdeln(1));    }
  170.  
  171. /* delete n lines. starting with the current line */
  172. bufdeln(n)    int n;
  173. {    int    k,oldline;
  174.     char    *oldbufp;
  175.     /* remember current buffer parameters */
  176.     oldline = bufline;
  177.     oldbufp = bufp;
  178.     /* scan for first line after deleted lines */
  179.     k = 0;
  180.     while ((n--) > 0)    {
  181.         if (bufatbot())
  182.             break;
  183.         if (bufdn() == ERR)    {
  184.             bufline = oldline;
  185.             oldbufp = bufp;
  186.             return(ERR);
  187.         }
  188.         ++k;
  189.     }
  190.     /* compress buffer.  update pointers */
  191.     bufmovup(bufp,bufpmax-1,bufp-oldbufp);
  192.     bufpmax = bufpmax - (bufp - oldbufp);
  193.     bufp = oldbufp;
  194.     bufline = oldline;
  195.     bufmaxln = bufmaxln - k;
  196.     bufcflag = YES;
  197.     return(OK);
  198. }
  199.  
  200. /* replace current line with the line that
  201.  * p points to.  The new line is of length n.
  202.  */
  203. bufrepl(p,n)    char *p;    int n;
  204. {    int    oldlen,k;
  205.     char    *nextp;
  206.     /* do not replace null line. just insert */
  207.     if (bufatbot())
  208.         return(bufins(p,n));
  209.     /* point nextp at start of next line */
  210.     if (bufdn() == ERR)
  211.         return(ERR);
  212.     nextp = bufp;
  213.     if (bufup() == ERR)
  214.         return(ERR);
  215.     /* allow for CR at end */
  216.     n = n + 1;
  217.     /* see how to move buffer below us;
  218.      * up, down, or not at all.
  219.      */
  220.     oldlen = nextp - bufp;
  221.     if (oldlen < n)    {
  222.         /* move buffer down */
  223.         if (bufext(n - oldlen) == ERR)
  224.             return(ERR);
  225.         bufpmax = bufpmax + n - oldlen;
  226.     }
  227.     else    if (oldlen > n)    {
  228.             /* move buffer up */
  229.             bufmovup(nextp,bufpmax - 1,oldlen - n);
  230.             bufpmax = bufpmax - (oldlen - n);
  231.         }
  232.     /* put new line in the hole we just made */
  233.     k = 0;
  234.     while (k < (n-1))
  235.         bufp[k] = p[k++];
  236.     bufp[k] = CR;
  237.     bufcflag = YES;
  238.     return(OK);
  239. }
  240.  
  241. /* copy current line into buffer that p points to.
  242.  * the maximum size of that buffer is n.
  243.  * return k = length of line in the main buffer.
  244.  * if k > n then truncate n - k characters and only
  245.  * return n characters in the caller's buffer.
  246.  */
  247. bufgetln(p,n)    char *p;    int n;
  248. {    int    k;
  249.     /* last line is always null */
  250.     if (bufatbot())
  251.         return(0);
  252.     /* copy line as long as it is not too long */
  253.     k = 0;
  254.     while (k < n)    {
  255.         if (*(bufp + k) == CR)
  256.             return(k);
  257.         *(p + k) = *(bufp+k);
  258.         ++k;
  259.     }
  260.     /* count length but move no more characters */
  261.     while (*(bufp + k) != CR)
  262.         ++k;
  263.     return(k);
  264. }
  265.  
  266. /* move buffer down (towards HIGH addresses) */
  267. bufmovdn(from,to,length)    char *from,*to;    int length;
  268. {
  269.     /* this code needs to be very fast.
  270.      * use an assembly language routine.
  271.      */
  272.     sysmovdn(to-from+1,to+length,to);
  273. }
  274.  
  275. /* move buffer up (towards LOW addresses) */
  276. bufmovup(from,to,length)    char *from,*to;    int length;
  277. {
  278.     /* this code must be very fast.
  279.      * use a assembly language routines;
  280.      */
  281.     sysmovup(to-from + 1,from - length, from);
  282. }
  283.  
  284. /* return true if at bottom of buffer.
  285.  * NOTE 1: the last line of the buffer is always null.
  286.  * NOTE 2: the last line number is always bufmaxln + 1.
  287.  */
  288. bufatbot()
  289. {    return(bufline > bufmaxln);    }
  290.  
  291. /* return true if at bottom or at the last real line before
  292.  * the bottom.
  293.  */
  294. bufnrbot()
  295. {    return(bufline >= bufmaxln);    }
  296.  
  297. /* return true if at top of buffer */
  298. bufattop()
  299. {    return(bufline == 1);    }
  300.  
  301. /* put nlines from buffer starting with line topline at
  302.  * position topy of the screen.
  303.  */
  304. bufout(topline,topy,nlines)    int topline,topy,nlines;
  305. {    int    l,p;
  306.     /* remember buffer's state */
  307.     l = bufline;
  308.     p = bufp;
  309.     /* write out one line at a time */
  310.     while ((nlines--) > 0)    {
  311.         outxy(0,topy++);
  312.         bufoutln(topline++);
  313.     }
  314.     /* restore buffer's state */
  315.     bufline = l;
  316.     bufp = p;
  317. }
  318.  
  319. /* print line of main buffer on screen */
  320. bufoutln(line)    int line;
  321. {
  322.     /* error message does NOT go on prompt line */
  323.     if (bufgo(line) == ERR)    {
  324.         outm(DELD);
  325.         outdeol();
  326.         return;
  327.     }
  328.     /* blank out lines below last line of buffer */
  329.     if (bufatbot())
  330.         outdeol();
  331.     /* write one formatted line out */
  332.     else    {
  333.         fmtsout(bufp,0);
  334.         outdeol();
  335.     }
  336. }
  337.  
  338. /* simple memory version of bufext.
  339.  * create a hole in buffer at current line.
  340.  * length is the size of the hole.
  341.  */
  342. bufext(length)    int length;
  343. {
  344.     /* make sure there is room for more */
  345.     if ((bufpmax + length) >= bufend)    {
  346.         outm(MBFUL);
  347.         return(ERR);
  348.     }
  349.     /* move lines below current line down */
  350.     bufmovdn(bufp, bufpmax - 1,length);
  351.     bufpmax = bufpmax + length;
  352.     return(OK);
  353. }
  354.  
  355. /* end module ed10/ccc */
  356.